package com.example.spring_secutity.config;

import com.example.spring_secutity.filter.JwtRequestFilter;
import com.example.spring_secutity.handler.AuthenticationEntryPointImpl;
import com.example.spring_secutity.handler.MyAccessDeniedHandler;
import com.example.spring_secutity.handler.MyAuthenticationFailHandler;
import com.example.spring_secutity.handler.MyAuthenticationSuccessHandler;
import com.example.spring_secutity.service.impl.DBUserDetailsService;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@Configuration
@EnableWebSecurity
public class SecurityConfig {
    @Resource
    DBUserDetailsService userDetailsService;

    @Resource
    MyAuthenticationSuccessHandler successHandler;

    @Resource
    MyAuthenticationFailHandler failHandler;

    @Resource
    JwtRequestFilter jwtRequestFilter;

    @Resource
    AuthenticationEntryPointImpl authenticationEntryPoint;
    @Resource
    MyAccessDeniedHandler myAccessDeniedHandler;
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        //自定义配置信息
        //配登录页面
        http
                .authorizeHttpRequests(request ->
                        request.requestMatchers("/dologin", "/doLogin","/fail")
                                .permitAll()
                                .anyRequest().authenticated())//开放两个接口，一个注册，一个登录，其余均要身份认证
                .formLogin(AbstractHttpConfigurer::disable)//取消默认登录页面的使用
                .logout(AbstractHttpConfigurer::disable)//取消默认登出页面的使用
                .csrf(AbstractHttpConfigurer::disable)//禁用csrf保护，前后端分离不需要
                //.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))//禁用session，因为我们已经使用了JWT
                .httpBasic(AbstractHttpConfigurer::disable)//禁用httpBasic，因为我们传输数据用的是post，而且请求体是JSON
                .addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class)//添加自定义过滤器
                .exceptionHandling(exceptionHandling->{
                    exceptionHandling.authenticationEntryPoint(authenticationEntryPoint);
                    exceptionHandling.accessDeniedHandler(myAccessDeniedHandler);
                })//.accessDeniedHandler(new MyAccessDeniedHandler())

        ;

        return http.build();

    }

    @Bean
    @Autowired
    public AuthenticationManager authenticationManager(@Qualifier(value="passwordEncoder")PasswordEncoder passwordEncoder){
        DaoAuthenticationProvider provider =new DaoAuthenticationProvider();
        //指定自定义的userDetailService 的实现
        provider.setUserDetailsService(userDetailsService);
        //指定密码加密方法
        provider.setPasswordEncoder(passwordEncoder);
        return  new ProviderManager(provider);
    }


/*    @Bean
    public UserDetailsService userDetailsService() {
        UserDetails user =
                User.withDefaultPasswordEncoder()
                        .username("zhangsan")
                        .password("123456")
                        .roles("USER")
                        .build();

        return new InMemoryUserDetailsManager(user);
    }*/

/*    @Bean
    public BCryptPasswordEncoder bCryptPasswordEncoder(){
        return new BCryptPasswordEncoder();
    }*/

    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }
}
